package org.compiere.process;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.lang.StringBuffer;
import java.math.BigDecimal;

import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.I_BPM_Project;
import org.compiere.model.MBPMForm;
import org.compiere.model.MBPMFormCell;
import org.compiere.model.MBPMFormCode;
import org.compiere.model.MBPMFormColumn;
import org.compiere.model.MBPMFormLine;
import org.compiere.model.MBPMFormValues;
import org.compiere.model.MBPMParameters;
import org.compiere.model.MBPMProject;
import org.compiere.model.MFormula;
import org.compiere.model.MParameter;
import org.compiere.model.MParameterLine;
import org.compiere.model.MTable;
import org.compiere.model.MVariable;
import org.compiere.model.X_BPM_FormCell;
import org.compiere.model.X_BPM_FormColumn;
import org.compiere.model.X_BPM_FormLine;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Trx;


public class BPM_CalcFormValues extends SvrProcess {

	/* Current context			*/
	public Properties m_ctx;
	/*	Optional Transaction 	*/
	public String	m_trxName = null;
	/* */
	public int BPM_Form_ID = 0;
	/* */
	private int AD_Org_ID = 0;
	/* */
	public int BPM_Project_ID = 0;  
	
	public int BPM_VersionBudget_ID=0;
	/* */
	public boolean IsSummary = false;  
	
	public boolean IsRunningTotal = false;

	public MBPMForm form = null;
	public MBPMFormLine formLine[] = null;
	public MBPMFormCell formCell[] = null;
	/* */
	
	@Override
	protected void prepare() {

		m_ctx = getCtx();
		m_trxName = get_TrxName();
		BPM_Form_ID = getRecord_ID();
		AD_Org_ID=1000000;
		
		ProcessInfoParameter[] para = getParameter();
		for (int i = 0; i < para.length; i++)	{
			String name = para[i].getParameterName();
			if (name == null); 
				//
			else if ("BPM_Form_ID".equals(para[i].getParameterName()))
				BPM_Form_ID = para[i].getParameterAsInt();
			else if ("BPM_Project_ID".equals(para[i].getParameterName()))
				BPM_Project_ID = para[i].getParameterAsInt();
			else if ("BPM_VersionBudget_ID".equals(para[i].getParameterName()))
				BPM_VersionBudget_ID = para[i].getParameterAsInt();
			else if ("IsSummary".equals(para[i].getParameterName()))
				IsSummary = para[i].getParameterAsBoolean();
			else if ("IsRunningTotal".equals(para[i].getParameterName()))
				IsRunningTotal = para[i].getParameterAsBoolean();
			else
			{
				log.log(Level.INFO, "Unknown Parameter: " + name);
			}
		}
		if (IsSummary) AD_Org_ID=0;
	}

	@Override
	protected String doIt() throws Exception {
		MBPMForm[] forms;
		if (IsRunningTotal) {
			forms = MBPMForm.getForms(BPM_VersionBudget_ID,AD_Org_ID);
			if (forms.length == 0)
				return "Нет форм с настройками на данный бюджетный календарь";
			for(MBPMForm form: forms)
			{
				BPM_Form_ID = form.getBPM_Form_ID();
				CalculateForm();
			}
		} else
			CalculateForm();
		return "Перерасчет выполнен успешно.";
	}
	
	private MParameterLine getLineParameter(int BSC_Parameter_ID){
		
		CLogger log = CLogger.getCLogger (MParameterLine.class);
		MParameterLine result = null; //new MParameterLine(m_ctx, 0, m_trxName);
		String sql = "SELECT BSC_ParameterLine_ID FROM BSC_ParameterLine WHERE isActive = 'Y' AND BSC_Parameter_ID = ? ";
		PreparedStatement pstmt = null;
		ResultSet rs = null;		
		int iPLID=0;
		try {
			pstmt = DB.prepareStatement(sql,m_trxName);
			pstmt.setInt (1, BSC_Parameter_ID);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				iPLID=rs.getInt(1);
				//result = new MParameterLine(Env.getCtx(),rs,m_trxName);
			}
		} catch (SQLException e) {
			log.log(Level.SEVERE, "MParameterLine: ", e);
		} finally {
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}	
		if (iPLID>0) result= new MParameterLine(Env.getCtx(),iPLID,m_trxName);
		return result;
	}
	
	private LinkedHashMap<String, Object> getParameters(int AD_Table_ID, int Record_ID, LinkedHashMap<String, Object> param){
		
		MBPMParameters[] parameters = MBPMParameters.getLines(m_ctx, AD_Table_ID, Record_ID, m_trxName);
		
		String in = "";
		int counter = 0;
		boolean isChanged = false;
		
		String type = parameters.length > 0 ? parameters[0].getColumnName() : "";
		
		for(MBPMParameters par: parameters){
			
			isChanged = !type.equals(par.getColumnName());
			
			if(!isChanged)
			{
				if(counter > 0)
					in += ", ";
				
				counter++;
			}
			else
			{
				counter = 1;
				in = "";
			}
			in += par.getValue1();
			
			if(par.getOperation().trim().toLowerCase().equals("between") && par.getValue2() != null && !par.getValue2().isEmpty())
				in += " AND ".concat(par.getValue2());
			
			param.put(par.getColumnName(), in);
			
			type = par.getColumnName();
		}
		
		if(BPM_Project_ID != MBPMProject.TempProjectID && BPM_Project_ID != 0)
			param.put(I_BPM_Project.COLUMNNAME_BPM_Project_ID, String.valueOf(BPM_Project_ID));
		
		return param;
	}

	public void Consolidation(){
		DB.executeUpdate("DELETE FROM BPM_FormValues WHERE AD_Client_ID = 1000000 AND AD_Org_ID = 0"
				+" AND BPM_Project_ID="+BPM_Project_ID+" AND BPM_Form_ID="+BPM_Form_ID, null);
		int BPM_Form2_ID = new BigDecimal(form.get_Value("BPM_Form2_ID").toString()).intValue();
		StringBuffer sql = new StringBuffer("");
		for(MBPMFormLine line: formLine){
			if (line.isExclude()) continue;
			MBPMFormColumn[] columns = MBPMFormCode.getColumns(getCtx(), form.getBPM_FormCode_ID(), m_trxName);
			//
			List<String> list = new ArrayList<String>();
			//
			for(MBPMFormColumn column: columns){
				MBPMFormCell cellBP = MBPMFormCell.getCell(Env.getCtx(), column.get_ID(), line.get_ID(), m_trxName);
				sql.setLength(0);
				sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
						"WHEN 'null' THEN 0 " +
						"WHEN 'NaN' THEN 0 " +
						"WHEN 'Infinity' THEN 0 " +
						"WHEN '-Infinity' THEN 0 " +
						"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
						+", MAX(AD_Org_ID), CASE MAX(ad_org_id) WHEN 1000007 THEN"
						+		" (SELECT MAX(bpm_formvalues_id) from bpm_formvalues " 
						+		" 	WHERE ad_org_id = 1000007 "
						+		"	AND BPM_FormLine_ID = "+line.get_ID()
						+		"   AND bpm_formcolumn_id = "+column.get_ID()
						+		"	AND BPM_Project_ID = "+BPM_Project_ID +")"
						+		" ELSE 0 END "
						+"\n FROM BPM_FormValues"
						+"\n WHERE AD_Org_ID<>1000006 AND BPM_FormLine_ID = "+line.get_ID()
						+"\n AND bpm_formcolumn_id = "+column.get_ID()
						+"\n AND BPM_Project_ID = "+BPM_Project_ID);

				if(line.get_ID()==1000308)
				{
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
							"WHEN 'null' THEN 0 " +
							"WHEN 'NaN' THEN 0 " +
							"WHEN 'Infinity' THEN 0 " +
							"WHEN '-Infinity' THEN 0 " +
							"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
							+", MAX(AD_Org_ID), CASE MAX(ad_org_id) WHEN 1000007 THEN"
							+		" (SELECT MAX(bpm_formvalues_id) from bpm_formvalues " 
							+		" 	WHERE ad_org_id = 1000007 "
							+		"	AND BPM_FormLine_ID = "+line.get_ID()
							+		"   AND bpm_formcolumn_id = "+column.get_ID()
							+		"	AND BPM_Project_ID = "+BPM_Project_ID +")"
							+		" ELSE 0 END "
							+"\n FROM BPM_FormValues"
							+"\n WHERE AD_Org_ID NOT IN(1000000,1000006)" 
							+"\n AND BPM_FormLine_ID = "+line.get_ID()
							+"\n AND bpm_formcolumn_id = "+column.get_ID()
							+"\n AND BPM_Project_ID = "+BPM_Project_ID);
				}
				if(line.get_ID()==1000323 || line.get_ID()==1000043 || line.get_ID()==1000042)
				{
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
							"WHEN 'null' THEN 0 " +
							"WHEN 'NaN' THEN 0 " +
							"WHEN 'Infinity' THEN 0 " +
							"WHEN '-Infinity' THEN 0 " +
							"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
							+", MAX(AD_Org_ID), CASE MAX(ad_org_id) WHEN 1000007 THEN"
							+		" (SELECT MAX(bpm_formvalues_id) from bpm_formvalues " 
							+		" 	WHERE ad_org_id = 1000007 "
							+		"	AND BPM_FormLine_ID = "+line.get_ID()
							+		"   AND bpm_formcolumn_id = "+column.get_ID()
							+		"	AND BPM_Project_ID = "+BPM_Project_ID +")"
							+		" ELSE 0 END "
							+"\n FROM BPM_FormValues"
							+"\n WHERE AD_Org_ID=1000000" 
							+"\n AND BPM_FormLine_ID = "+line.get_ID()
							+"\n AND bpm_formcolumn_id = "+column.get_ID()
							+"\n AND BPM_Project_ID = "+BPM_Project_ID);
				}
				//
				BigDecimal bSum = Env.ZERO;
				int BPM_FormValues_ID=0;
				boolean cons = false;
				PreparedStatement pstmt = null;
				ResultSet rs = null;		
				try {
					pstmt = DB.prepareStatement(sql.toString(),m_trxName);
					rs = pstmt.executeQuery();
					if (rs.next()) {
						if ("NaN".equals(rs.getString(1))) bSum = Env.ZERO;
						else bSum =rs.getBigDecimal(1);
						if (1000007==rs.getInt(2)) {
							BPM_FormValues_ID=rs.getInt(3);
							cons=true;
						}
						
					}
				} catch (SQLException e) {
					log.log(Level.SEVERE, "CellValue: ", e);
				} finally {
					DB.close(rs, pstmt);
					rs = null; pstmt = null;
				}
				//
				
				//
// +++++++++++++++++ ВГО ++++++++++++++++++++++++++
				int BPM_FormColumn2_ID = column.get_ValueAsInt("BPM_FormColumn2_ID");
				if ((BPM_Form2_ID>0)&&(BPM_FormColumn2_ID>0)) {
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(REPLACE(CellValue,' ','')::NUMERIC),0) "
							+"\n FROM BPM_FormValues"
							+"\n WHERE BPM_FormLine_ID = (SELECT BPM_FormLine_ID FROM BPM_FormLine WHERE "
							+"\n BPM_Form_ID = "+BPM_Form2_ID+" AND LineNo = "+line.getLineNo()+")"
							+"\n AND BPM_FormColumn_ID = "+BPM_FormColumn2_ID
							+"\n AND BPM_Project_ID = "+BPM_Project_ID);
					BigDecimal bSum2 = Env.ZERO;
					pstmt = null;
					rs = null;		
					try {
						pstmt = DB.prepareStatement(sql.toString(),m_trxName);
						rs = pstmt.executeQuery();
						if (rs.next()) {
							if ("NaN".equals(rs.getString(1))) bSum2 = Env.ZERO;
							else bSum2 =rs.getBigDecimal(1);
						}
					} catch (SQLException e) {
						log.log(Level.SEVERE, "CellValue: ", e);
					} finally {
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
					if (bSum2!=null) {
						if (bSum!=null) bSum=bSum.subtract(bSum2);
						else bSum=bSum2.negate();
					}
				}
// ----------------- ВГО --------------------------

// +++++++++++++++++ Дивиденды ++++++++++++++++++++++++++
				if ((BPM_Form2_ID>0)&&(line.getBPM_FormLine2_ID()>0)) {
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
							"WHEN 'null' THEN 0 " +
							"WHEN 'NaN' THEN 0 " +
							"WHEN 'Infinity' THEN 0 " +
							"WHEN '-Infinity' THEN 0 " +
							"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
							+"\n FROM BPM_FormValues"
							+"\n WHERE BPM_FormLine_ID = "+line.getBPM_FormLine2_ID()
							+"\n AND bpm_formcolumn_id = "+column.get_ID()
							+"\n AND BPM_Project_ID = "+BPM_Project_ID
							+"\n AND AD_Org_ID <> 1000007");
					BigDecimal bSum2 = Env.ZERO;
					pstmt = null;
					rs = null;		
					try {
						pstmt = DB.prepareStatement(sql.toString(),m_trxName);
						rs = pstmt.executeQuery();
						if (rs.next()) {
							if ("NaN".equals(rs.getString(1))) bSum2 = Env.ZERO;
							else bSum2 =rs.getBigDecimal(1);
						}
					} catch (SQLException e) {
						log.log(Level.SEVERE, "CellValue: ", e);
					} finally {
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
					if (bSum2!=null) {
						if (bSum!=null) bSum=bSum.subtract(bSum2);
					}
				}
// ----------------- Дивиденды --------------------------
				if(line.getBPM_FormLine_ID()==1000035 || line.get_ID()==1000036 
						|| line.get_ID()==1000038 || line.get_ID()==1000040)
				{
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
							"WHEN 'null' THEN 0 " +
							"WHEN 'NaN' THEN 0 " +
							"WHEN 'Infinity' THEN 0 " +
							"WHEN '-Infinity' THEN 0 " +
							"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
							+", MAX(AD_Org_ID), CASE MAX(ad_org_id) WHEN 1000007 THEN"
							+		" (SELECT MAX(bpm_formvalues_id) from bpm_formvalues " 
							+		" 	WHERE ad_org_id = 1000007 "
							+		"	AND BPM_FormLine_ID = "+1000040
							+		"   AND bpm_formcolumn_id = "+column.get_ID()
							+		"	AND BPM_Project_ID = "+BPM_Project_ID +")"
							+		" ELSE 0 END "
							+"\n FROM BPM_FormValues"
							+"\n WHERE AD_Org_ID=1000006" 
							+"\n AND BPM_FormLine_ID = "+1000040
							+"\n AND bpm_formcolumn_id = "+column.get_ID()
							+"\n AND BPM_Project_ID = "+BPM_Project_ID);
					
					BigDecimal bSum2 = Env.ZERO;
					pstmt = null;
					rs = null;		
					try {
						pstmt = DB.prepareStatement(sql.toString(),m_trxName);
						rs = pstmt.executeQuery();
						if (rs.next()) {
							bSum2 =rs.getBigDecimal(1);
						}
					} catch (SQLException e) {
						log.log(Level.SEVERE, "CellValue: ", e);
					} finally {
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
					
					BigDecimal bpm_Share = DB.getSQLValueBD(get_TrxName(), "SELECT BPM_Share FROM BPM_Subs WHERE AD_Org_ID = ?", 1000006);
					
					if(line.get_ID()==1000040)
					{
						if(bSum2.equals(Env.ZERO))
							list.add("0");
						else
							list.add((bSum2.multiply(bpm_Share)).divide(new BigDecimal(100)).toString());
					}
					
					if(line.getBPM_FormLine_ID() == 1000035 || line.get_ID()==1000036 || line.get_ID()==1000038 || line.get_ID()==1000040)
					{
						if((bSum2!=null)&&(!bSum2.equals(Env.ZERO)))
						{
							bSum = bSum.add((bSum2.multiply(bpm_Share)).divide(new BigDecimal(100)));
						}
					}
				}
				//--->
				if(line.getBPM_FormLine_ID()==1000036 || line.getBPM_FormLine_ID()==1000038 || line.getBPM_FormLine_ID()==1000040)
				{
					sql.setLength(0);
					sql.append("SELECT COALESCE(SUM(CASE CellValue	" +
							"WHEN 'null' THEN 0 " +
							"WHEN 'NaN' THEN 0 " +
							"WHEN 'Infinity' THEN 0 " +
							"WHEN '-Infinity' THEN 0 " +
							"ELSE REPLACE(CellValue,' ','')::NUMERIC END ::NUMERIC),0) "
							+", MAX(AD_Org_ID), CASE MAX(ad_org_id) WHEN 1000007 THEN"
							+		" (SELECT MAX(bpm_formvalues_id) from bpm_formvalues " 
							+		" 	WHERE ad_org_id = 1000007 "
							+		"	AND BPM_FormLine_ID = "+1000024
							+		"   AND bpm_formcolumn_id = "+column.get_ID()
							+		"	AND BPM_Project_ID = "+BPM_Project_ID +")"
							+		" ELSE 0 END "
							+"\n FROM BPM_FormValues"
							+"\n WHERE AD_Org_ID=1000000" 
							+"\n AND BPM_FormLine_ID = "+1000024
							+"\n AND bpm_formcolumn_id = "+column.get_ID()
							+"\n AND BPM_Project_ID = "+BPM_Project_ID);
					
					BigDecimal bSum2 = Env.ZERO;
					pstmt = null;
					rs = null;		
					try {
						pstmt = DB.prepareStatement(sql.toString(),m_trxName);
						rs = pstmt.executeQuery();
						if (rs.next()) {
							bSum2 =rs.getBigDecimal(1);
						}
					} catch (SQLException e) {
						log.log(Level.SEVERE, "CellValue: ", e);
					} finally {
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
					if((bSum2!=null)&&(!bSum2.equals(Env.ZERO)))
					{
						bSum = bSum.add(bSum2.negate());
					}
				}
				//<--
				
				MBPMFormValues value = new MBPMFormValues(m_ctx, 0, m_trxName);
				if ((bSum!=null)&&(!bSum.equals(Env.ZERO))) {
					value.setBPM_Form_ID(line.getBPM_Form_ID());
					value.setBPM_FormLine_ID(line.getBPM_FormLine_ID());
					value.setBPM_FormColumn_ID(column.getBPM_FormColumn_ID());
					value.setBPM_VersionBudget_ID(BPM_VersionBudget_ID);
					value.setBPM_Project_ID(BPM_Project_ID);
					value.setBPM_FormCell_ID(cellBP.get_ID());
					value.setAD_Org_ID(AD_Org_ID);
					value.setCellValue(bSum.toString());
					if (cons) value.setAlternateValue(String.valueOf(BPM_FormValues_ID));
					value.saveEx();
				}
			}
			//
			if(list.size()>0)
			{
				String[] values = list.toArray(new String[list.size()]);
				int i=0;
				for(MBPMFormColumn formColumn : MBPMFormCode.getColumns(m_ctx, 1000008, get_TrxName()))
				{
					MBPMFormCell cell = MBPMFormCell.getCell(m_ctx, formColumn.get_ID(), 1000308, get_TrxName());
					
					MBPMFormValues value = null;
					value = MBPMFormValues.getFormValueLine(1000308, formColumn.get_ID(), BPM_VersionBudget_ID, BPM_Project_ID);
					if(value==null)
					{
						value = new MBPMFormValues(m_ctx, 0, m_trxName);
						value.setBPM_Form_ID(1000010);
						value.setBPM_FormLine_ID(1000308);
						value.setBPM_FormColumn_ID(formColumn.getBPM_FormColumn_ID());
						value.setBPM_VersionBudget_ID(BPM_VersionBudget_ID);
						value.setBPM_Project_ID(BPM_Project_ID);
						value.setBPM_FormCell_ID(cell.get_ID());
						value.setAD_Org_ID(AD_Org_ID);
					}
					value.setCellValue(values[i].toString());
					value.saveEx();
					i++;
				}
			}
			//
		}	
	}
	
	public String CalculateForm(){
		form = new MBPMForm(m_ctx, BPM_Form_ID, m_trxName);
		formLine = MBPMForm.getLines(m_ctx, form.getBPM_Form_ID(), m_trxName);
		if (IsSummary) {
			Consolidation();
			return "Перерасчет консолидации выполнен успешно.";
		}
		boolean isBOForm = form.getName().contains("БО");
		boolean is5BOpForm = form.getName().contains("5БО(п)");
		BigDecimal bThousand = new BigDecimal("1000");
		StringBuffer sql = new StringBuffer("");
		StringBuffer cellvalue = new StringBuffer("");
		long time1= System.nanoTime();
		for(MBPMFormLine l: formLine){
			long time2 = System.nanoTime();
			long timeSpent = time2-time1;
			System.out.println(timeSpent/1000000000);
			
			int BSC_Parameter_ID = 0; 
			int BPM_FormValues_ID=0;
			formCell = MBPMFormLine.getLines(m_ctx, l.getBPM_FormLine_ID(), m_trxName);
			for(MBPMFormCell cell: formCell){
				
				time2 = System.nanoTime();
				// Получим показатель ячейки
				BSC_Parameter_ID = cell.getBSC_Parameter_ID();
				/*MParameter pCell = new MParameter(m_ctx, BSC_Parameter_ID, get_TrxName());
				if (!pCell.getZeroParameterLine().getValue().equals("0")) {
					pCell.getZeroParameterLine().setValue("0");
					pCell.saveEx(); // clear
				}*/

				timeSpent = System.nanoTime()-time2;
				System.out.print(timeSpent/1000000+"-A-");
				
				// устанавливаем приоритет. 1. Ячейка, 2. Строка, 3. Колонка
				if(!cell.isParameter()) {
					if(l.isParameter() && !cell.getBPM_FormColumn().isHead()) {
						BSC_Parameter_ID = l.getBSC_Parameter_ID();
					}
					else if(cell.getBPM_FormColumn().isParameter()) {
						BSC_Parameter_ID = cell.getBPM_FormColumn().getBSC_Parameter_ID();
					}
				}
				
				if(cell.getCellValue().equals(Env.ZERO)){
					LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
					
					timeSpent = System.nanoTime()-time2;
					System.out.print(timeSpent/1000000+"-AA-");
					
					MParameterLine parLine = getLineParameter(BSC_Parameter_ID);
					if (parLine==null) continue;
					timeSpent = System.nanoTime()-time2;
					System.out.print(timeSpent/1000000+"-AB-");

					if (parLine.isFormula()||(parLine.isImported() && parLine.getPFR_Calculation_ID() > 0)) {
						getParameters(MTable.getTable_ID(X_BPM_FormColumn.Table_Name), cell.getBPM_FormColumn_ID(), obj);
						getParameters(MTable.getTable_ID(X_BPM_FormLine.Table_Name), cell.getBPM_FormLine_ID(), obj);
						getParameters(MTable.getTable_ID(X_BPM_FormCell.Table_Name), cell.get_ID(), obj);
					}

					timeSpent = System.nanoTime()-time2;
					System.out.print(timeSpent/1000000+"-B-");
					
					//
					String result = "0";
					if(parLine.isFormula()){
						HashMap<String,Object> args = new HashMap<String,Object>(); 
						Map<String, MVariable> map = parLine.getVariables();
						for(String key: map.keySet()){
							MVariable var = map.get(key);  
							if(var.getBSC_Parameter_ID() > 0) {
								
								obj = new LinkedHashMap<String, Object>();
								int BPM_FormColumn_ID = cell.getBPM_FormColumn_ID();
								int BPM_FormLine_ID = cell.getBPM_FormLine_ID();
								
								if (cell.getBPM_FormColumn().isParameter()) {
									BPM_FormLine_ID = cell.getBPM_FormLine_ID();
									MBPMFormColumn[] fCol = MBPMFormColumn.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), get_TrxName());
									for(MBPMFormColumn cl: fCol){
										getParameters(MTable.getTable_ID(X_BPM_FormColumn.Table_Name), cl.getBPM_FormColumn_ID(), obj);
									}
									BPM_FormColumn_ID = (fCol.length > 0 ? fCol[0].getBPM_FormColumn_ID():0);
								}  
								if (cell.getBPM_FormLine().isParameter() && !cell.getBPM_FormColumn().isHead()) {
									BPM_FormColumn_ID = cell.getBPM_FormColumn_ID();
									MBPMFormLine[] fLine = MBPMFormLine.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), m_trxName);
									
									for(MBPMFormLine cl: fLine){
										getParameters(MTable.getTable_ID(X_BPM_FormLine.Table_Name), cl.getBPM_FormLine_ID(), obj);
									}
									BPM_FormLine_ID = (fLine.length > 0 ? fLine[0].getBPM_FormLine_ID():0);
								}
								if (cell.isParameter()) {
									int _BSC_Parameter_ID = var.getBSC_Parameter_ID();
									MBPMFormCell[] _cc = MBPMFormCell.getLinesParameter(m_ctx, _BSC_Parameter_ID, get_TrxName());
									if (_cc.length > 0) {
										BPM_FormColumn_ID = _cc[0].getBPM_FormColumn_ID();
										BPM_FormLine_ID = _cc[0].getBPM_FormLine_ID();
									}
								}
								
								MBPMFormCell[] varCell = MBPMFormCell.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), get_TrxName());
								MBPMFormLine[] varLine = MBPMFormLine.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), get_TrxName());
								MBPMFormColumn[] varCol = MBPMFormColumn.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), get_TrxName());
								if (varCell.length > 0) {
									if (MBPMFormCell.getBPM_Form_ID(varCell[0].getBPM_FormCell_ID()) != BPM_Form_ID){
										BPM_FormColumn_ID = varCell[0].getBPM_FormColumn_ID();
										BPM_FormLine_ID = varCell[0].getBPM_FormLine_ID();
									}
								} else if (varLine.length > 0 && varLine[0].getBPM_Form_ID() != BPM_Form_ID) {
									throw new AdempiereException("Нельзя однозначно определить ячейку другой формы. Параметер формулы {"+key+"} ссылается на линию из другой формы. Ошибка расчетов в линии \""+l.getName()+"\"");
								} else if (varCol.length > 0 && MBPMFormColumn.getBPM_Form_ID(varCol[0].getBPM_FormColumn_ID()) != BPM_Form_ID) {
									MBPMFormColumn cl = new MBPMFormColumn(m_ctx, BPM_FormColumn_ID, get_TrxName());
									throw new AdempiereException("Нельзя однозначно определить ячейку другой формы. Параметер формулы {"+key+"} ссылается на колонку из другой формы. Ошибка расчетов в колонке \""+cl.getName()+"\"");
								}
								
								MBPMFormCell cc  = MBPMFormCell.getCell(m_ctx, BPM_FormColumn_ID, BPM_FormLine_ID, get_TrxName());
								
								if (BPM_FormLine_ID > 0 && BPM_FormColumn_ID > 0) {
									getParameters(MTable.getTable_ID(X_BPM_FormColumn.Table_Name), cc.getBPM_FormColumn_ID(), obj);
									getParameters(MTable.getTable_ID(X_BPM_FormLine.Table_Name), cc.getBPM_FormLine_ID(), obj);
									getParameters(MTable.getTable_ID(X_BPM_FormCell.Table_Name), cc.get_ID(), obj);
								}

								
								if(!cc.isParameter() && (var.getParameter().getZeroParameterLine().isImported())) {
									MBPMFormCell[] cTemp = MBPMFormCell.getLinesParameter(m_ctx, var.getBSC_Parameter_ID(), get_TrxName());
									
									if (cTemp.length > 0) {
										cc = (cTemp.length> 0? cTemp[0] : null);
										getParameters(MTable.getTable_ID(X_BPM_FormColumn.Table_Name), cc.getBPM_FormColumn_ID(), obj);
										getParameters(MTable.getTable_ID(X_BPM_FormLine.Table_Name), cc.getBPM_FormLine_ID(), obj);
										getParameters(MTable.getTable_ID(X_BPM_FormCell.Table_Name), cc.get_ID(), obj);
									} else {
										getParameters(MTable.getTable_ID(X_BPM_FormColumn.Table_Name), cell.getBPM_FormColumn_ID(), obj);
									}
									String value1 = var.getParameter().getZeroParameterLine().calculate(obj, is5BOpForm);
									args.put(key, value1);
								} else {
									MParameter p = new MParameter(m_ctx, cc.getBSC_Parameter_ID(),get_TrxName());
									String value1 = p.getZeroParameterLine().getValue(obj, is5BOpForm);
									args.put(key, value1);
								}

								MFormula f = parLine.getFormula();
								
								result = MFormula.calc(f.getFormula(), args);
								
							}
						}
					}else{
						result = parLine.calculate(obj, is5BOpForm);
					}
					
					/*if (!pCell.getZeroParameterLine().getValue().equals(result)) {
						pCell.getZeroParameterLine().setValue(result);
						pCell.getZeroParameterLine().saveEx();
					}*/
					if (isBOForm&&(!result.equals("0"))) {
						BigDecimal bResult = new BigDecimal(result);
						bResult=bResult.divide(bThousand, 2, BigDecimal.ROUND_HALF_DOWN);
						result=bResult.toString();
					}
					
					timeSpent = System.nanoTime()-time2;
					System.out.print(timeSpent/1000000+"-C-");
					
					BPM_FormValues_ID=0;
					sql.setLength(0); cellvalue.setLength(0);
					sql.append("SELECT BPM_FormValues_ID, CellValue FROM BPM_FormValues " 
					    + "\n WHERE AD_Org_ID="+AD_Org_ID 
						+ "\n AND BPM_FormLine_ID="+l.getBPM_FormLine_ID()
						+ "\n AND BPM_FormColumn_ID="+cell.getBPM_FormColumn_ID()
						+ "\n AND BPM_VersionBudget_ID="+BPM_VersionBudget_ID
						+ "\n AND BPM_Project_ID="+BPM_Project_ID);
					PreparedStatement pstmt = null;
					ResultSet rs = null;	
					try
					{
						pstmt = DB.prepareStatement(sql.toString(),get_TrxName());
						rs = pstmt.executeQuery();
						if(rs.next())
							BPM_FormValues_ID= rs.getInt(1);
							cellvalue.append(rs.getString(2));
					}
					catch (SQLException e)
					{
						CLogger.get().log(Level.INFO, "SQL = "+sql, e);
					}
					finally
					{
						DB.close(rs, pstmt);
						rs = null; pstmt = null;
					}
					
					timeSpent = System.nanoTime()-time2;
					System.out.println(timeSpent/1000000+"-D-");
					
					if (BPM_FormValues_ID==0) {
						if (result.equals("0")||result.equals("0.0")||result.equals("0.00")||result.equals("0E+2")) continue;  
					}else {
						if (cellvalue.toString().equals(result)) continue;
					}
					
					//MBPMFormValues value = MBPMFormValues.getFormValueLine(l.getBPM_FormLine_ID(), cell.getBPM_FormColumn_ID(), form.getBPM_VersionBudget_ID(), BPM_Project_ID);
					MBPMFormValues value = new MBPMFormValues(m_ctx, BPM_FormValues_ID, m_trxName);
					value.setBPM_Form_ID(l.getBPM_Form_ID());
					value.setBPM_FormLine_ID(l.getBPM_FormLine_ID());
					value.setBPM_FormColumn_ID(cell.getBPM_FormColumn_ID());
					value.setBPM_VersionBudget_ID(form.getBPM_VersionBudget_ID());
					value.setBPM_Project_ID(BPM_Project_ID);
					value.setBPM_FormCell_ID(cell.get_ID());
					value.setAD_Org_ID(l.getAD_Org_ID());
						
					try{
						value.setCellValue(result);
					}catch(Exception ex){
						value.setAlternateValue(result);
					}
					finally{
						value.saveEx();
					}
				}else{
					//pCell.getZeroParameterLine().setValue(String.valueOf(cell.getCellValue()));
					//pCell.getZeroParameterLine().saveEx();
					//cell.setisParameter(true);
					//cell.saveEx();
					
					//value.setCellValue(cell.getCellValue().toString());
					//value.saveEx();
				}
				
			}
		}
		
		// 
		/*Trx trx = Trx.get(m_trxName, false);
		trx.commit();
		trx.close();*/
		long time2 = System.nanoTime();
		long timeSpent = time2-time1;
		System.out.println(timeSpent/1000000000);
		return "Перерасчет выполнен успешно.";
		
	}
		
}
